package io.renren.common.utils;

import io.renren.modules.basedata.entity.Abstract;
import io.renren.modules.basedata.entity.Data;
import io.renren.modules.basedata.entity.Tbl_cardBlackList;
import io.renren.modules.basedata.entity.Validate;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;


/**
 * 解压缩工具
 * @author Administrator
 *
 */
public class ZIPUtil {
	 /**
     * 解压缩zip包
     * @param zipFilePath zip文件的全路径
     * @param unzipFilePath 解压后的文件保存的路径
     * @param includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含；false-不包含
     */
	 @SuppressWarnings("unchecked")
	public static void unzip(String zipFilePath, String unzipFilePath, boolean includeZipFileName) throws Exception{
		 if (StringUtils.isEmpty(zipFilePath) || StringUtils.isEmpty(unzipFilePath))
	        {
	            throw new Exception("路径参数为空");           
	        }
		 File zipFile = new File(zipFilePath);  
		 //如果解压后的文件保存路径包含压缩文件的文件名，则追加该文件名到解压路径 
		 if (includeZipFileName) {
			 String fileName = zipFile.getName();  
			 if (StringUtils.isNotEmpty(fileName)) {
				 fileName = fileName.substring(0, fileName.lastIndexOf("."));  
			 } 
			 unzipFilePath = unzipFilePath + File.separator + fileName; 
		 }
		 //创建解压缩文件保存的路径
		 File unzipFileDir = new File(unzipFilePath);
		 if (!unzipFileDir.exists() || !unzipFileDir.isDirectory())  {
			 unzipFileDir.mkdirs();  
		 }
		
		 //开始解压  
		 ZipEntry entry = null;  
		 
		 //文件解压后保存的文件全路径
		 String entryFilePath = null;
		
		 //解压后保存的文件夹路径  
		 String entryDirPath = null; 
		 File entryFile = null;
		 File entryDir = null;  
		 
		 int index = 0, count = 0, bufferSize = 1024;  
		 byte[] buffer = new byte[bufferSize];  
		 BufferedInputStream bis = null;  
		 BufferedOutputStream bos = null;
		 ZipFile zip = new ZipFile(zipFile);  
		 Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>)zip.entries();  
		 //循环对压缩包里的每一个文件进行解压 
		 while(entries.hasMoreElements())  {
			 entry = entries.nextElement();  
		
			 //构建压缩包中一个文件解压后保存的文件全路径  
			 entryFilePath = unzipFilePath + File.separator + entry.getName();  
			 //构建解压后保存的文件夹路径  
			 index = entryFilePath.lastIndexOf(File.separator);  
			 if (index != -1)  {
				 entryDirPath = entryFilePath.substring(0, index);  
			 }else{
				 entryDirPath = "";  
			 }
			 entryDir = new File(entryDirPath);  
			 		    
	         //创建解压文件 
	         entryFile = new File(entryFilePath);
	         //如果文件夹路径不存在，则创建文件夹  
			 if (!entryDir.exists() || !entryDir.isDirectory())  {
				 entryDir.mkdirs();  
			 }
			 if (entryFile.exists())  {
				 //删除已存在的目标文件 
				 entryFile.delete();   
			 }

			 //写入文件  
			 bos = new BufferedOutputStream(new FileOutputStream(entryFile));  
			 bis = new BufferedInputStream(zip.getInputStream(entry));  
			 while ((count = bis.read(buffer, 0, bufferSize)) != -1)  {
				 bos.write(buffer, 0, count);  
			 }
			 bos.flush();  
			 bos.close();          
		 }
		 zip.close();
	   }
	 
	    /** 
	     * 移动文件到指定目录 
	     * @param oldPath String 如：c:/fqf.txt 
	     * @param newPath String 如：d:/fqf.txt 
	     */ 
		 public static void moveFile(String oldPath, String newPath) { 
		       copyFile(oldPath, newPath); 
		       delFile(oldPath); 
	
		 } 
		 /** 
		     * 获取json文件中的字符串
		     * @param
		     */ 
		 public static String getjsonStr(String filepath){
			 BufferedReader reader = null;
			 String jsonStr = "" ;
			 try{
				 FileInputStream fileInputStream = new FileInputStream(filepath);
				 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
				 reader = new BufferedReader(inputStreamReader,20*1024*1024);
				 String tempString = "";
				 while((tempString = reader.readLine()) != null){
					 jsonStr += tempString;
				 }
				 reader.close();
				 }catch(IOException e){
				 e.printStackTrace();
				 }finally{
				 if(reader != null){
				 try {
				 reader.close();
				 } catch (IOException e) {
				 e.printStackTrace();
				 }
				 }
				 } 
			return jsonStr;
		 }

	   /** 
	     * 删除文件 
	     * @param filePathAndName String 文件路径及名称 如c:/fqf.txt 
	     * @param
	     * @return boolean 
	     */ 
	   public static void delFile(String filePathAndName) { 
	       try { 
	           String filePath = filePathAndName; 
	           filePath = filePath.toString(); 
	           File myDelFile = new File(filePath); 
	           System.gc();    //加上确保文件能删除，不然可能删不掉  
	           myDelFile.delete(); 

	       } 
	       catch (Exception e) { 
	           System.out.println("删除文件操作出错"); 
	           e.printStackTrace(); 

	       } 

	   } 

	     /** 
	     * 复制单个文件 
	     * @param oldPath String 原文件路径 如：c:/fqf.txt 
	     * @param newPath String 复制后路径 如：f:/fqf.txt 
	     * @return boolean 
	     */ 
	   public static void copyFile(String oldPath, String newPath) { 
	       try { 
	           int bytesum = 0; 
	           int byteread = 0; 
	           File oldfile = new File(oldPath); 
	           if (oldfile.exists()) { //文件存在时 
	               InputStream inStream = new FileInputStream(oldPath); //读入原文件 
	               FileOutputStream fs = new FileOutputStream(newPath); 
	               byte[] buffer = new byte[1444]; 
	               while ( (byteread = inStream.read(buffer)) != -1) { 
	                   bytesum += byteread; //字节数 文件大小 
	                   System.out.println(bytesum); 
	                   fs.write(buffer, 0, byteread); 
	               } 
	               inStream.close(); 
	           } 
	       } 
	       catch (Exception e) { 
	           System.out.println("复制单个文件操作出错"); 
	           e.printStackTrace(); 

	       } 

	   } 
	   
	    /**
	     * 获取目录下所有文件并按名称排序 升序
	     * @param path
	     * @return
	     * @throws Exception
	     */
	    public static List<File> getFiles(String path) throws Exception {
	    //目标集合fileList
	    List<File> fileList = new ArrayList<File>();
	    File file = new File(path);
	    if(file.isDirectory()){//检查file是否是文件夹
	    File []files = file.listFiles();//返回某个目录下所有文件和目录的绝对路径，返回的是File数组
	    for(File fileIndex:files){
		    //如果这个文件是目录，则进行递归搜索
		    if(fileIndex.isDirectory()){
		    	getFiles(fileIndex.getPath());
		    }else {
		    //如果文件是普通文件，则将文件句柄放入集合中
		    	fileList.add(fileIndex);
		    }
	    	}
	    	//对文件列表按名称排序
		    Collections.sort(fileList, new Comparator<File>() {
		        @Override
		        public int compare(File o1, File o2) {
		            if (o1.isDirectory() && o2.isFile())
		                return -1;
		            if (o1.isFile() && o2.isDirectory())
		                return 1;
		            return o1.getName().compareTo(o2.getName());
		        }
		    });
	    }
	    return fileList;
	 }

	 /**
	  * 解析压缩包下json文件转换相应实体类对象
	  * @param <T>
	  * @param zipfile
	  * @param classObj
	  * @return
	  * @throws Exception
	  */
	 @SuppressWarnings({ "unchecked", "deprecation" })
	public static <T> List<T> analysisJson(File zipfile,Class<T> classObj)throws Exception{
		 List<T> result = new ArrayList<T>();
		 List<T> result1 = new ArrayList<T>();
		 String jsonstr=null;
		 String jsonStr = "";
		 ZipEntry childentry = null;
		 int count = 0, bufferSize = 1024;  
		 byte[] buffer = new byte[bufferSize];  
		 BufferedInputStream bis = null;  
		 ZipFile childzip = new ZipFile(zipfile); 
		 Enumeration<ZipEntry> childentries = (Enumeration<ZipEntry>)childzip.entries(); 
		 String fileName =zipfile.getName();  
		 if (StringUtils.isNotEmpty(fileName)) {
			 fileName = fileName.substring(0, fileName.lastIndexOf("."));  
		 } 
		 //获取文件名称作为版本号
		 String version=fileName.split("_")[0];
    	 while(childentries.hasMoreElements())  {
    		 childentry = childentries.nextElement();  
			 bis = new BufferedInputStream(childzip.getInputStream(childentry));  
			 while ((count = bis.read(buffer, 0, bufferSize)) != -1)  {
				 jsonstr=new String(buffer, 0, count);
				 jsonStr=jsonStr+jsonstr;
			 }
//			 result1 = (List<T>)JSONArray.parseArray(jsonStr,classObj);
			 result1 = (List<T>) JSONArray.toList(JSONArray.fromObject(jsonStr), classObj);
			 result.addAll(result1);
    	 }
    	 childzip.close();//关闭压缩文件，否则不能删除压缩包  
    	 zipfile.delete();//删除压缩包  
//    	 result=(List<T>)JSONArray.toList(JSONArray.fromObject(jsonstr), classObj);
//    	 result=(List<T>)JSONArray.toList(JSONArray.fromObject(jsonStr), classObj);
		 return result;
	 }
	 /**
	  * 解析校验文件
	  * @param validateFile
	  * @return
	  * @throws Exception
	  */
	 @SuppressWarnings("unchecked")
	public static Validate analysisValidateJson(File validateFile)throws Exception{
		 Validate validate= new Validate();
		 String jsonstr=null;
		 int count = 0, bufferSize = 1024;  
		 byte[] buffer = new byte[bufferSize];  
		 InputStream in = null;  
		 in = new FileInputStream(validateFile);  
		 while ((count = in.read(buffer, 0, bufferSize)) != -1)  {
			 jsonstr=new String(buffer, 0, count);
		 }
		 in.close();
		 // JSON转换
		 JSONObject jsonObj = JSONObject.fromObject(jsonstr);
			
		 Map<String, Class> classMap = new HashMap<String, Class>();
         classMap.put("data", Data.class);
         classMap.put("abstract", Abstract.class);
         // 将JSON转换成WeatherBean_Baidu  
         validate = (Validate) JSONObject.toBean(jsonObj,Validate.class, classMap);
		 return validate;
	 }
	 
	 /**
	     * 递归删除目录下的所有文件及子目录下所有文件
	     * @param dir 将要删除的文件目录
	     * @return boolean Returns "true" if all deletions were successful.
	     *                 If a deletion fails, the method stops attempting to
	     *                 delete and returns "false".
	     */
	    public static boolean deleteDir(File dir) {
	       
	    	if (dir.isDirectory()) {
	            String[] children = dir.list();
	            //递归删除目录中的子目录下
	            for (int i=0; i<children.length; i++) {
	                boolean success = deleteDir(new File(dir, children[i]));
	                if (!success) {
	                    return false;
	                }
	            }
	        }
	        // 目录此时为空，可以删除
	        return dir.delete();
	    }
	 
	
	 //测试
	 public static void main(String[] args) {
		 String zipFilePath = "F:\\ziptest\\zipPath\\20171010.zip";  
		 String workFilePath = "F:\\ziptest\\unzipPath\\work"; 
		 String successFilePath = "F:\\ziptest\\unzipPath\\success"; 
		 String errorFilePath = "F:\\ziptest\\unzipPath\\error"; 
		 
		 
		 String zworkFilePath = "F:\\ziptest\\unzipPath\\zwork"; 
		 String zsuccessFilePath = "F:\\ziptest\\unzipPath\\zsuccess"; 
		 String zerrorFilePath = "F:\\ziptest\\unzipPath\\zerror"; 
		 //父级文件名
		 String parentfileName=zipFilePath.split("\\\\")[3];
		 //父级路径
		 String parentpath=parentfileName.substring(0, parentfileName.lastIndexOf(".")); 
		 try {
			
			//全量
			
			
			moveFile(zipFilePath, workFilePath+"\\"+parentfileName);
			unzip(workFilePath+"\\"+parentfileName, workFilePath, true);//()
			List<File> fileList =getFiles(workFilePath+"\\"+parentpath);
			boolean flag=false;
			for (int i = 0; i < fileList.size(); i++) {
				List<Tbl_cardBlackList> cardBlackList=analysisJson(fileList.get(i),Tbl_cardBlackList.class);
				System.out.println(cardBlackList.size());
				flag=true;
			}
			delFile(workFilePath+"\\"+parentpath);
			if(flag){
				moveFile(workFilePath+"\\"+parentfileName, successFilePath+"\\"+parentfileName);
			}else{
				moveFile(workFilePath+"\\"+parentfileName, errorFilePath+"\\"+parentfileName);
			}
			
			
			
			//增量
			
			//1、转移至工作目录
			moveFile(zipFilePath, zworkFilePath+"\\"+parentfileName);
			//2、解压各个版本文件
			unzip(zworkFilePath+"\\"+parentfileName, zworkFilePath, true);
			//3、获取各个版本文件
			List<File> zfileList =getFiles(zworkFilePath+"\\"+parentpath);
			boolean zflag=true;
			//4、并顺序执行各版本文件
			for (int i = 0; i < zfileList.size(); i++) {
				//5、解压当前版本文件
				String currentName=zfileList.get(i).getName();
				String currtentPath=zworkFilePath+"\\"+parentpath+"\\"+currentName.substring(0, currentName.lastIndexOf("."));
				unzip(zfileList.get(i).getAbsolutePath(), zworkFilePath+"\\"+parentpath, true);
				//6、获取当前版本数据包和校验文件
				List<File> zfileListdata =getFiles(currtentPath);
				for (int j = 0; j < zfileListdata.size(); j++) {
					String Name=zfileListdata.get(j).getName();
					if (Name.indexOf(".json")!=-1) {
						//解析校验文件至内存
						Validate validate =analysisValidateJson(zfileListdata.get(j));
						//删除校验文件
						zfileListdata.get(j).delete();
					}else{
						//解压数据包
						unzip(currtentPath+"\\"+zfileListdata.get(j).getName(), currtentPath, false);
						//删除数据包
						delFile(currtentPath+"\\"+zfileListdata.get(j).getName());
					}
				}
				//7、取出各省增量包文件
				List<File> zfileListfxf =getFiles(currtentPath);
				for (int k = 0; k < zfileListfxf.size(); k++) {
					List<Tbl_cardBlackList> cardBlackList=analysisJson(zfileListfxf.get(k),Tbl_cardBlackList.class);
					System.out.println(cardBlackList.size());
				}
			
				//8、按规则取出校验卡号
				List<String> cardlist =null;
				
				//9、解析校验文件 并比较文件是否一致
				
				//10、删除临时目录
				delFile(currtentPath);
				//11、删除当前版本文件
				zfileList.get(i).delete();
			}
			
			
			delFile(zworkFilePath+"\\"+parentpath);
			if(zflag){
				moveFile(zworkFilePath+"\\"+parentfileName, zsuccessFilePath+"\\"+parentfileName);
			}else{
				moveFile(zworkFilePath+"\\"+parentfileName, zerrorFilePath+"\\"+parentfileName);
			}
			
			
			//
//			deleteDir(new File(""));
			
		 } catch (Exception e) {
			e.printStackTrace();
		 }  
	}
}
